package m6;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;

public class RPClient {
    static Channel c;
    static BlockingQueue<String> bq = new ArrayBlockingQueue<>(10);

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //创建连接
        ConnectionFactory f = new ConnectionFactory();
        f.setHost("192.168.64.140");
        // 5672 端口，客户端应收发消息的端口
        // 15672 端口。管理控制台界面的访问端口
        f.setPort(5672);
        f.setUsername("admin");
        f.setPassword("admin");
        Connection con = f.newConnection();
        c = con.createChannel();  //通信的通道

        while (true){
            System.out.println("求第几个斐波那契数：");
            int n = new Scanner(System.in).nextInt();
            long fbnq = f(n);
            System.out.println("结果："+fbnq);
        }
    }

    private static long f(int n) throws IOException, InterruptedException {
        // 创建调用队列rpc_queue
        c.queueDeclare("rpc_queue", false, false, false, null);
        // 创建随机队列，用来接受执行结果
        String queue = c.queueDeclare().getQueue();//服务器自动提供参数
        // 产生一个关联id
        String cid = UUID.randomUUID().toString();
        // 发送调用消息，需要携带返回队列名和关联id
        AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().replyTo(queue).correlationId(cid).build();
        c.basicPublish("", "rpc_queue",props , String.valueOf(n).getBytes());
        // 从返回队列接收服务返回的结果
        c.basicConsume(queue, true, (consumerTag,message) -> {
            String result = new String(message.getBody());
            String cid2 = message.getProperties().getCorrelationId();
            //模拟关联id
            //真实逻辑应该用集合存储关联id，这里和集合中的关联id来对比
            if(cid.equals(cid2)){
                // 把结果放入阻塞队列，主线程会从阻塞队列获取结果
                bq.add(result);
            }
        }, (consumerTag) -> {});
        // 可以在这里继续执行其他运算，不必等待- -

        // 直到需要结果时，再获取计算结果
        return Long.valueOf(bq.take());
    }
}
